﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace DeSleeper.Library
{

    /// <summary>
    /// A wake up request data object.  Contains the necessary information to wake up a host once a suitable proxy is found.
    /// </summary>
    public class WakeUpRequest : IXmlSerializable, IEquatable<WakeUpRequest>
    {
        /// <summary>
        /// The target host name.  Will be used if <c>MacAddress</c> is empty or null.
        /// </summary>
        /// <remarks>
        /// A host name may not be sufficient to perform a wake up because a host name
        /// cannot be resolved to a MAC address without access to the target's network
        /// card.  MAC address must have been cached for a host name only to succeed.
        /// 
        /// If a <see cref="MacAddress"/> is filled, this field should still be filled in
        /// because it might be necessary to recognize an appropriate host via subnet.
        /// </remarks>
        public string HostName { get; set; }

        /// <summary>
        /// MacAddress of the target.  If blank or null, then system must rely on 
        /// <see cref="HostName"/>.
        /// </summary>
        public PhysicalAddress MacAddress { get; set; }

        XmlSchema IXmlSerializable.GetSchema()
        {
            var schema = new XmlSchema();
            schema.Items.Add(new XmlSchemaElement {Name = "HostName", SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema")});
            schema.Items.Add(new XmlSchemaElement { Name = "MacAddress", SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema") });
            return schema;
        }

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            reader.ReadStartElement();
            HostName = reader.ReadElementString("HostName");
            MacAddress = PhysicalAddress.Parse(reader.ReadElementString("MacAddress"));
            reader.ReadEndElement();
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            writer.WriteElementString("HostName", HostName);
            writer.WriteElementString("MacAddress", MacAddress.ToString());
        }

        public bool Equals(WakeUpRequest other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.HostName, HostName) && Equals(other.MacAddress, MacAddress);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(WakeUpRequest)) return false;
            return Equals((WakeUpRequest)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int result = (HostName != null ? HostName.GetHashCode() : 0);
                result = (result*397) ^ (MacAddress != null ? MacAddress.GetHashCode() : 0);
                return result;
            }
        }
    }
}